#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
#include <text.hpp>
// 单个通信信道（进程+自己的匿名管道）
static int default_num=6;
class channel
{
public:
    channel(pid_t id, int n)
        : _subid(id), _fd(n)
    {
        _name += "-channel" + std::to_string(_subid) + "[" + std::to_string(_fd) + "]";
    }
    std::string& Getname()
    {
        return _name;
    }
    void Send(int x)
    {
        int ret=write(_fd,&x,sizeof(x));
        if(ret<0)
        {
            std::cout<<"写入任务码失败！"<<std::endl;
        }
    }
    ~channel()
    {
    }

private:
    // 子进程的PID+对应匿名管道的读端+匿名管道的名字
    pid_t _subid;
    int _fd;
    std::string _name;
};

// 对所有通信信道进行管理
class channelmanager
{
public:
    channelmanager()
    :_next(0)
    {}
    void Insert(id_t id, int n)
    {
        _channels.emplace_back(id, n);
    }
    channel& Select()
    {
        return _channels[_next++%_channels.size()];
    } 
private:
    std::vector<channel> _channels;
    int _next;
};

// 进程池
class processpool
{
public:
    processpool()
    {
    }
    ~processpool()
    {
    }
    void Run()
    {
        // 当进行Run时默认已经进行了Start创建了所有的子进程
        //这里Run的作用就是选出任务（任务码）并选择负载均衡的信道将任务吗写入匿名管道
        int taskcode=_tm.Select();
        std::cout<<"选择了一个任务码："<<taskcode<<std::endl;
        channel& c=_cm.Select();
        std::cout<<"选择了一个通信信道："<<c.Getname()<<std::endl;
        c.Send(taskcode);
    }
    void Work(int n)
    {
        while (1)
        {
            int n;
            int ret = read(3, &n, sizeof(n));
            if (ret > 0)
            {
                if (ret == sizeof(n))
                {
                    // 读正确了
                    std::cout << "子进程 " << getpid() << "收到了一个任务码 " << n << std::endl;
                    //_tm[n-1]();应该是_tm::tasks[n-1]()因为tasks是私有的
                    //我们这里设计一个执行方法
                    _tm.Execute(n);
                }
                else
                {
                    continue;
                }
            }
            else if (ret < 0)
            {
                std::cout << "read fail!" << std::endl;
                break;
            }
            else
            {
                std::cout << "父进程（写端）关闭，子进程（读端）也关闭" << std::endl;
                break;
            }
        }
    }
    void Start()
    {
        while (default_num)
        {
            int fd[2] = {0};
            int ret = pipe(fd);
            pid_t id = fork();
            if (id < 0)
            {
                std::cout << "fork fail!" << std::endl;
                exit(1);
            }
            else if (id == 0)
            {
                // 子进程
                close(fd[1]);
                Work(fd[0]);
                exit(0);
            }
            else
            {
                // 父进程
                close(fd[0]);
                _cm.Insert(id, fd[1]);
                default_num--;
                exit(0);
            }
        }
    }

private:
    channelmanager _cm;
    teskmanager _tm;
};